package com.guohao.server;

import cn.hutool.core.lang.Console;
import cn.hutool.http.server.SimpleServer;
import com.guohao.annotation.Controller;
import com.guohao.annotation.RequestMapping;
import com.guohao.http.MethodInfo;
import com.guohao.http.ServerMapping;
import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

/**
 * Hello
 */
public class HTTP {

  private static final Logger log = LoggerFactory.getLogger(HTTP.class);

  public static void run(Integer port) {
    String className = Thread.currentThread().getStackTrace()[2].getClassName();
    SimpleServer simpleServer = new SimpleServer(port);
    ConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
        .setScanners(
            new TypeAnnotationsScanner(),
            new SubTypesScanner(false)
        ).setUrls(ClasspathHelper.forPackage(className.substring(0, className.lastIndexOf("."))))
        .filterInputsBy(new FilterBuilder()
            .includePackage(className.substring(0, className.lastIndexOf("."))));
    Reflections reflections = new Reflections(configurationBuilder);
    Set<Class<?>> types = reflections
        .getTypesAnnotatedWith(Controller.class);
    for (Class<?> type : types) {
      Method[] declaredMethods = type.getDeclaredMethods();
      Controller controller = type.getAnnotation(Controller.class);
      Map<String, MethodInfo> requestInfoMap = new HashMap<>();
      for (Method method : declaredMethods) {
        if (method.isAnnotationPresent(RequestMapping.class)) {
          RequestMapping annotation = method.getAnnotation(RequestMapping.class);
          String path = controller.value()+annotation.value();
          if (requestInfoMap.containsKey(path.concat("@").concat(annotation.method().name()))) {
            throw new IllegalStateException(
                "路径：" + annotation.method().name() + " " + path + " 已经存在！");
          }
          try {
            requestInfoMap
                .put(path.concat("@").concat(annotation.method().name()),
                    new MethodInfo(path, annotation.method(), method,
                        type.getConstructor().newInstance()));
            Console.log("映射：{} {} ——> {}", annotation.method().name(), path, method.getName());
          } catch (Exception e) {
            log.error(e.getMessage(), e);
          }
        }
      }
      simpleServer.createContext("/", new ServerMapping(requestInfoMap));
    }
    simpleServer.start();
  }
}
